package com.mxgraph.swing.test;

/*
Swing, Second Edition
by Matthew Robinson, Pavel Vorobiev

*/

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.text.SimpleDateFormat;

import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;

public class FileTree3 
  extends JFrame 
{
  public static final ImageIcon ICON_COMPUTER = 
    new ImageIcon("computer.gif");
  public static final ImageIcon ICON_DISK = 
    new ImageIcon("disk.gif");
  public static final ImageIcon ICON_FOLDER = 
    new ImageIcon("folder.gif");
  public static final ImageIcon ICON_EXPANDEDFOLDER = 
    new ImageIcon("expandedfolder.gif");

  protected JTree  m_tree;
  protected DefaultTreeModel m_model;
  protected JTextField m_display;

  protected JPopupMenu m_popup;
  protected Action m_action;
  protected TreePath m_clickedPath;

  public FileTree3()
  {
    super("Directories Tree [Tool Tips]");
    setSize(400, 300);

    DefaultMutableTreeNode top = new DefaultMutableTreeNode(
      new IconData(ICON_COMPUTER, null, "Computer"));

    DefaultMutableTreeNode node;
    File[] roots = File.listRoots();
    for (int k=0; k<roots.length; k++)
    {
      node = new DefaultMutableTreeNode(new IconData(ICON_DISK, 
        null, new FileNode(roots[k])));
      top.add(node);
      node.add(new DefaultMutableTreeNode( new Boolean(true) ));
    }

    m_model = new DefaultTreeModel(top);
// NEW
    m_tree = new JTree(m_model)
    {
      public String getToolTipText(MouseEvent ev) 
      {
        if(ev == null)
          return null;
        TreePath path = m_tree.getPathForLocation(ev.getX(), 
          ev.getY());
        if (path != null)
        {
          FileNode fnode = getFileNode(getTreeNode(path));
          if (fnode==null)
            return null;
          File f = fnode.getFile();
          return (f==null ? null : f.getPath());
        }
        return null;
      }
    };
    ToolTipManager.sharedInstance().registerComponent(m_tree);

                m_tree.putClientProperty("JTree.lineStyle", "Angled");

    TreeCellRenderer renderer = new 
      IconCellRenderer();
    m_tree.setCellRenderer(renderer);

    m_tree.addTreeExpansionListener(new 
      DirExpansionListener());

    m_tree.addTreeSelectionListener(new 
      DirSelectionListener());

    m_tree.getSelectionModel().setSelectionMode(
      TreeSelectionModel.SINGLE_TREE_SELECTION); 
    m_tree.setShowsRootHandles(true); 
    m_tree.setEditable(false);

    JScrollPane s = new JScrollPane();
    s.getViewport().add(m_tree);
    getContentPane().add(s, BorderLayout.CENTER);

    m_display = new JTextField();
    m_display.setEditable(false);
    getContentPane().add(m_display, BorderLayout.NORTH);

    m_popup = new JPopupMenu();
    m_action = new AbstractAction() 
    { 
      public void actionPerformed(ActionEvent e)
      {
        if (m_clickedPath==null)
          return;
        if (m_tree.isExpanded(m_clickedPath))
          m_tree.collapsePath(m_clickedPath);
        else
          m_tree.expandPath(m_clickedPath);
      }
    };
    m_popup.add(m_action);
    m_popup.addSeparator();

    Action a1 = new AbstractAction("Delete") 
    { 
      public void actionPerformed(ActionEvent e)
      {
                                m_tree.repaint();
        JOptionPane.showMessageDialog(FileTree3.this, 
          "Delete option is not implemented",
          "Info", JOptionPane.INFORMATION_MESSAGE);
      }
    };
    m_popup.add(a1);

    Action a2 = new AbstractAction("Rename") 
    { 
      public void actionPerformed(ActionEvent e)
      {
                                m_tree.repaint();
        JOptionPane.showMessageDialog(FileTree3.this, 
          "Rename option is not implemented",
          "Info", JOptionPane.INFORMATION_MESSAGE);
      }
    };
    m_popup.add(a2);
    m_tree.add(m_popup);
    m_tree.addMouseListener(new PopupTrigger());

    WindowListener wndCloser = new WindowAdapter()
    {
      public void windowClosing(WindowEvent e) 
      {
        System.exit(0);
      }
    };
    addWindowListener(wndCloser);
    
    setVisible(true);
  }

  DefaultMutableTreeNode getTreeNode(TreePath path)
  {
    return (DefaultMutableTreeNode)(path.getLastPathComponent());
  }

  FileNode getFileNode(DefaultMutableTreeNode node)
  {
    if (node == null)
      return null;
    Object obj = node.getUserObject();
    if (obj instanceof IconData)
      obj = ((IconData)obj).getObject();
    if (obj instanceof FileNode)
      return (FileNode)obj;
    else
      return null;
  }

  class PopupTrigger extends MouseAdapter
  {
    public void mouseReleased(MouseEvent e)
    {
      if (e.isPopupTrigger())
      {
        int x = e.getX();
        int y = e.getY();
        TreePath path = m_tree.getPathForLocation(x, y);
        if (path != null)
        {
          if (m_tree.isExpanded(path))
            m_action.putValue(Action.NAME, "Collapse");
          else
            m_action.putValue(Action.NAME, "Expand");
          m_popup.show(m_tree, x, y);
          m_clickedPath = path;
        }
      }
    }
  }

    // Make sure expansion is threaded and updating the tree model
    // only occurs within the event dispatching thread.
    class DirExpansionListener implements TreeExpansionListener
    {
        public void treeExpanded(TreeExpansionEvent event)
        {
            final DefaultMutableTreeNode node = getTreeNode(
                event.getPath());
            final FileNode fnode = getFileNode(node);

            Thread runner = new Thread() 
            {
              public void run() 
              {
                if (fnode != null && fnode.expand(node)) 
                {
                  Runnable runnable = new Runnable() 
                  {
                    public void run() 
                    {
                       m_model.reload(node);
                    }
                  };
                  SwingUtilities.invokeLater(runnable);
                }
              }
            };
            runner.start();
        }

        public void treeCollapsed(TreeExpansionEvent event) {}
    }

  class DirSelectionListener 
    implements TreeSelectionListener 
  {
    public void valueChanged(TreeSelectionEvent event)
    {
      DefaultMutableTreeNode node = getTreeNode(
        event.getPath());
      FileNode fnode = getFileNode(node);
      if (fnode != null)
        m_display.setText(fnode.getFile().
          getAbsolutePath());
      else
        m_display.setText("");
    }
  }

  public static void main(String argv[]) 
  {
    new FileTree3();
  }
}


